2023/12/234101字符

事件冒泡 & 事件捕获

<div style="width:300px;height:300px;background-color:#f00;margin:0 auto;" class="wrapper">wrapper
    <div style="width:200px;height:200px;background-color:#0f0" class="content">content
        <div style="width:100px;height:100px;background-color:#00f" class="box">box</div>
    </div>
</div>
  • 事件冒泡:结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)
var wrapper = document.getElementsByTagName('div')[0];
var content = document.getElementsByTagName('div')[1];
var box = document.getElementsByTagName('div')[2];
wrapper.addEventListener('click', function(){
    console.log('wrapper');  //--> wrapper  事件冒泡
}, false);
content.addEventListener('click', function(){
    console.log('content');  //--> content wrapper  事件冒泡
}, false);
box.addEventListener('click', function(){
    console.log('box');  //--> box content wrapper  事件执行
}, false);
  • 事件捕获(兼容新版浏览器(IE 没有),与事件冒泡相反) 结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自顶向下)
wrapper.addEventListener('click', function(){
    console.log('wrapper');  //--> wrapper  事件捕获
}, true);
content.addEventListener('click', function(){
    console.log('content');  //--> wrapper content  事件捕获
}, true);
box.addEventListener('click', function(){
    console.log('box');  //--> wrapper content box  事件执行
}, true);
// 事件捕获 --> 事件执行 --> 事件冒泡

focus,blur,change,submit,reset,select 等事件不冒泡

取消事件冒泡和默认事件

document.onclick = function () {
    console.log('你闲的呀');
}
wrapper.onclick = function (e) {
    e = e || window.event;  // IE e 事件在 window 下的 event
    console.log(e);  // 能够返回所有事件信息
    e.stopPropagation();  // 取消事件冒泡(IE9 及以下不兼容)
    e.cancelBubble = true;  // IE 取消事件冒泡
}

封装取消冒泡的函数 stopBubble(event)

function stopBubble (event) {
    event = e || window.enent;
    if (event.stopPropagation) {
        event.stopPropagation();
    } else {
        event.cancelBubble = true;
    }
}
wrapper.onclick = function () {
    stopBubble(e);  // 函数调用
}

右键出菜单事件

// 1.
document.oncontextmenu = function(){  // 右键出菜单事件
    console.log('a');
    return false;  // 取消右键菜单事件
}
// 2.
document.addEventListener('contextmenu', function(e){
    console.log('a');
    e.preventDefault();  // 取消右键菜单事件
    e.returnValue = false;  // IE 取消右键菜单事件
}, false);

封装阻止默认事件的函数 cancelHandler(event);

function cancelHandler(event){
    event = e || window.event;
    if(event.preventDefault){
        event.preventDefault();
    }else{
        event.returnValue = false;
    }
}

事件源对象

wrapper.onclick = function(e){
    var e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
}
<a herf="javascript:void(false)">demo</a>  <!-- 协议限定符  a 标签失去点击事件 == return false --> 
<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>
// 1. 浪费效率
var li = document.getElementsByTagName('li');
var len = li.length;
for(var i = 0; i < len; i ++){
    li[i].onclick = function(){
        console.log(this.innerText);
    }
}
// 2. 利用事件源对象
var ul = document.getElementsByTagName('ul')[0];
ul.onclick = function(){
    var e = e || window.event;
    var target = e.target || event.srcElement;
    console.log(target.innerText);
}